package com.gp.base.except;

import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.StrutsStatics;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.dao.DataAccessException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.gp.base.BaseAction;
import com.gp.base.filter.LoginPurviewCheckFilter;
import com.gp.base.util.StrUtil;
import com.gp.base.util.TimeUtil;
import com.gp.sys.domain.SysLog;
import com.gp.sys.domain.SysUser;
import com.gp.sys.manager.SysLogManager;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

/**
 * 
 * <li>类型名称：
 * <li>说明：异常拦截处理器，用户提交请求，服务器端的Action进行处理；当处理过程出现异常；
 * <li>本拦截器扑获Action抛出的所有类型的异常，根据用户请求的日志，系统根据情况返回到
 * <li>用户的请求页面或专门的异常显示页面
 * <li>创建人：曾明辉
 * <li>创建日期：2008-10-14
 * <li>修改人： 
 * <li>修改日期：
 */
public class ExceptionInterceptor extends AbstractInterceptor {
	
	private static Map<String, String> methodMap = new HashMap<String, String>();
	
	static{
		methodMap.put("save", "保存");
		methodMap.put("deleteById", "单个删除");
		methodMap.put("deleteByIds", "多个删除");
		methodMap.put("startUp", "启用");
		methodMap.put("giveUp", "弃用");
		methodMap.put("login", "登录");
	}
	/**
	 * 
	 */
	public String intercept(ActionInvocation invocation) throws Exception{
		String result = null;
		String errorMessage = null;  
		
		try{
			String message = this.getLogMessage(invocation);
			
			result = invocation.invoke();
			
			this.addSysLog(invocation, message);
		}
//		catch(BusinessException ex){//业务逻辑异常放在Action中捕获
//			errorMessage = ex.getMessage();
//		}
		catch(DataAccessException ex){
			errorMessage = "数据库操作失败！";
			ex.printStackTrace();
			throw ex;
		}
		catch(NullPointerException ex){
			errorMessage = "调用了未经初始化的对象或者是不存在的对象！";
			ex.printStackTrace();
			throw ex;
		}
		catch(IOException ex){
			errorMessage = "IO异常！";
			ex.printStackTrace();
			throw ex;
		}
		catch(ClassNotFoundException ex){
			errorMessage = "指定的类不存在！";
			ex.printStackTrace();
			throw ex;
		}
		catch(ArithmeticException ex){
			errorMessage = "数学运算异常！";
			ex.printStackTrace();
			throw ex;
		}
		catch(ArrayIndexOutOfBoundsException ex){
			errorMessage = "数组下标越界!";
			ex.printStackTrace();
			throw ex;
		}
		catch(IllegalArgumentException ex){
			errorMessage = "方法的参数错误！";
			ex.printStackTrace();
			throw ex;
		}
		catch(ClassCastException ex){
			errorMessage = "类型强制转换错误！";
			ex.printStackTrace();
			throw ex;
		}
		catch(SecurityException ex){
			errorMessage = "违背安全原则异常！";
			ex.printStackTrace();
			throw ex;
		}
		catch(SQLException ex){
			errorMessage = "操作数据库异常！";
			ex.printStackTrace();
			throw ex;
		}
		catch(NoSuchMethodError ex){
			errorMessage = "方法末找到异常！";
			ex.printStackTrace();
			throw ex;
		}
		catch(InternalError ex){
			errorMessage = "Java虚拟机发生了内部错误";
			ex.printStackTrace();
			throw ex;
		}
		catch(Exception ex){
			errorMessage = ex.getMessage();
			ex.printStackTrace();
			throw ex;
		}
		finally{
			if(invocation.getAction() instanceof BaseAction){
				BaseAction baseAction = (BaseAction)invocation.getAction();						
				baseAction.addActionError(errorMessage);
			}
		}
		return result;
	}
	
	/**
	 * 
	 * <li>方法名：addSysLog
	 * <li>@param invocation
	 * <li>返回类型：void
	 * <li>说明：
	 * <li>创建人：曾明辉
	 * <li>创建日期：2010-8-6
	 * <li>修改人： 
	 * <li>修改日期：
	 */
	private void addSysLog(ActionInvocation invocation, String message){
		ActionProxy proxy = invocation.getProxy();
		if(methodMap.containsKey(proxy.getMethod())){//需要记录日志
			SysLog log = new SysLog();
			log.setActionName(proxy.getActionName());
			log.setActionMethod(proxy.getMethod());
			log.setLogContent(message);
			
			Map session = invocation.getInvocationContext().getSession();
			Object user = session.get(LoginPurviewCheckFilter.USER_SESSION_NAME);
			if(user == null){
				return ;
			}
			else{
				if(user instanceof SysUser){
					SysUser indiMemb = (SysUser)user;
					log.setRegName(indiMemb.getRegNo());
					log.setRealName(indiMemb.getRealName());
				}
			}
			
			ActionContext actionContext = invocation.getInvocationContext();
			HttpServletRequest request= (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);      
			log.setUserIp(request.getRemoteAddr());
			
			Date sysDate = new Date();
			try {
				log.setLogTime(TimeUtil.toStrDateFromUtilDateByFormat(sysDate, "yyyy-MM-dd HH:mm:ss"));
			} catch (ParseException e) {
				log.setLogTime("");
			}
				
			
			WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
			SysLogManager sysLogManager = (SysLogManager)ctx.getBean("sysLogManager");
			
			sysLogManager.insert(log);
			
		}
	}
	/**
	 * 
	 * <li>方法名：getLogMessage
	 * <li>@param invocation
	 * <li>@return
	 * <li>返回类型：String
	 * <li>说明：
	 * <li>创建人：曾明辉
	 * <li>创建日期：2010-8-9
	 * <li>修改人： 
	 * <li>修改日期：
	 */
	private String getLogMessage(ActionInvocation invocation){
		ActionProxy proxy = invocation.getProxy();
		if(! (invocation.getAction() instanceof BaseAction)){
			return proxy.getActionName() + "：" + proxy.getMethod();
		}
		BaseAction action = (BaseAction)invocation.getAction();
		String method = proxy.getMethod();
		StringBuffer sb = new StringBuffer();
		if("login".equals(method)){
			sb.append(methodMap.get(method));
		}
		else{
			sb.append("【");
			sb.append(proxy.getActionName());
			sb.append("】");
			if("save".equals(method)){//保存
				Object entity = action.getEntity();
				if(action.isUpdate(entity)){
					sb.append("修改【");
				}
				else{
					sb.append("新增【");
				}
				sb.append(getEntityMessage(entity));
			}
			else{
				sb.append(methodMap.get(method));
				sb.append("【");
				if("deleteByIds".equals(method)){
					for (String id : action.getIds()) {
						sb.append(id + "；");
					}
				}
				else if("deleteById".equals(method) || "startUp".equals(method) || "giveUp".equals(method)){
					sb.append(action.getId());
				}
				else if("login".equals(method)){
					sb.append("");
				}
				else{
					Object entity = action.getEntity();
					sb.append(entity.toString());
				}
			}
	
			sb.append("】");
			if(sb.length()>2000){
				sb.delete(2000, sb.length()-1);
			}
		}
		return sb.toString();
	}
	
	/**
	 * 
	 * <li>方法名：getEntityMessage
	 * <li>@param entity
	 * <li>@return
	 * <li>返回类型：String
	 * <li>说明：
	 * <li>创建人：曾明辉
	 * <li>创建日期：2010-8-9
	 * <li>修改人： 
	 * <li>修改日期：
	 */
	private String getEntityMessage(Object entity){
		StringBuffer sb = new StringBuffer();
		Field fieldArr[] = entity.getClass().getDeclaredFields();
		BeanWrapper bw = new BeanWrapperImpl(entity);
		
		Object val = null;
		for (Field field : fieldArr) {
			val  = bw.getPropertyValue(field.getName());
			if(val != null ){
				if(val instanceof String ||val instanceof Integer || val instanceof Byte
					|| val instanceof Short || val instanceof Long
					|| val instanceof Float || val instanceof Double
					|| val instanceof Number){
					if(StrUtil.isNotEmpty(val.toString())){
						sb.append(field.getName());
						sb.append("：");
						sb.append(val.toString());
						sb.append("；");
					}
				}
				else if(val instanceof Set){
					Set objs = (Set)val;
					for (Object obj : objs) {
						sb.append(this.getEntityMessage(obj));
					}
				}
				else if(val instanceof Collection){
					Collection objs = (Collection)val;
					for (Object obj : objs) {
						sb.append(this.getEntityMessage(obj));
					}
				}
				else{
					sb.append(this.getEntityMessage(val));
				}
			}
		}
		
		return sb.toString();
	}
}
